package io.dbw.modules.utils.weixin;

import com.alibaba.fastjson.JSONObject;
import io.dbw.common.utils.CacheUtils;
import io.dbw.common.utils.CommParamUtils;
import io.dbw.common.utils.StringUtil;
import io.dbw.modules.utils.HttpUtils;
import io.dbw.modules.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信请求类
 *
 * @author fsh
 * @email
 * @date 2022-03-30 11:18:58
 */
@Slf4j
@Component
public class WeiXinUtil {
    /**
     * 生成accessToken
     *
     * @param code
     * @return
     */
    public static JSONObject getAccessToken(String code) {
        String param = "appid=" + CommParamUtils.appId + "&secret=" + CommParamUtils.appSecret
                + "&code=" + code + "&grant_type=authorization_code";
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token";
        JSONObject object = HttpUtils.httpGet(url, param);
        log.info("通过code获得accessToken--->" + object);
        return object;
    }

    /**
     * 获取ID和KEY信息
     *
     * @param code
     * @return openid + session_key + unionid (绑定了公共平台才会有)
     */
    public static JSONObject getSessionKey(String code) {
        String param = "appid=" + CommParamUtils.appId + "&secret=" + CommParamUtils.appSecret
                + "&js_code=" + code + "&grant_type=authorization_code";
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        JSONObject object = HttpUtils.httpGet(url, param);
        log.info("通过code获得-openid+session_key+unionid--->" + object);
        return object;
    }

    /**
     * 获取accessToken
     *
     * @return
     */
    public static synchronized String getAccessToken() {
        String param = "grant_type=client_credential&appid=" + CommParamUtils.appId + "&secret=" + CommParamUtils.appSecret;
        String url = "https://api.weixin.qq.com/cgi-bin/token";
        JSONObject httpGet = HttpUtils.httpGet(url, param);
        String accessToken = (String) httpGet.get("access_token");
        CacheUtils cacheUtils = CacheUtils.Instance.INSTANCE.getInstance();
        cacheUtils.put("access_token", accessToken, 3600 * 1000);
        log.info("WeiXinUtil---getAccessToken---" + accessToken);
        return accessToken;
    }

    /**
     * 获取ticket
     *
     * @return
     */
    public static String getTicket() {
        CacheUtils cacheUtils =  CacheUtils.Instance.INSTANCE.getInstance();
        String ticket = StringUtil.toString(cacheUtils.get("ticket"), "");
        if (StringUtils.isNotBlank(ticket)) {
            return ticket;
        }
        String token = WeiXinUtil.getAccessToken();
        String param = "access_token=" + token + "&type=jsapi";
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
        JSONObject httpGet = HttpUtils.httpGet(url, param);
        ticket = StringUtil.toString(httpGet.get("ticket"), "");
        cacheUtils.put("ticket", ticket, 3600 * 1000);
        return ticket;
    }

    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    public static Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = UUIDUtil.getUUID();
        String timestamp = UUIDUtil.getTimeMills();
        String string1;
        String signature = "";
        try {
            // 注意这里参数名必须全部小写，且必须有序
            string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "&timestamp=" + timestamp + "&url="
                    + url;

            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            log.error(e.toString());
        } catch (UnsupportedEncodingException e) {
            log.error(e.toString());
        }
        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        ret.put("appId", CommParamUtils.appId);
        return ret;
    }

}
